package com.xtaller.lazy.api.system;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xtaller.lazy.base.TApi;
import com.xtaller.lazy.lib.R;
import com.xtaller.lazy.lib.annotation.Permission;
import com.xtaller.lazy.lib.convert.J;
import com.xtaller.lazy.lib.convert.M;
import com.xtaller.lazy.lib.convert.V;
import com.xtaller.lazy.model.system.Authorities;
import com.xtaller.lazy.model.system.Module;
import com.xtaller.lazy.model.system.Role;
import com.xtaller.lazy.model.system.RoleAuth;
import com.xtaller.lazy.parameter.DocRole;
import com.xtaller.lazy.parameter.DocTree;
import com.xtaller.lazy.service.system.AuthoritiesService;
import com.xtaller.lazy.service.system.ModuleService;
import com.xtaller.lazy.service.system.RoleAuthService;
import com.xtaller.lazy.service.system.RoleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @version V1.0
 * @author: Taller
 * @date: 2019-04-09
 * @Description: 角色模块
 */
@Api(tags = "角色模块api")
@RestController
@RequestMapping("/v1/system")
public class RoleApi extends TApi {
    @Autowired private RoleService roleService;
    @Autowired private AuthoritiesService authoritiesService;
    @Autowired private ModuleService moduleService;
    @Autowired private RoleAuthService roleAuthService;

    private Map<String, String> baseVerify() {
        var verify = M.create("name", "名称不能为空");
        return verify;
    }

    @GetMapping("/role")
    @ApiOperation("读取数据")
    @Permission(authorities = "system-role-table")
    public Object table(@ApiParam("页码") @RequestParam(value = "page", required = false, defaultValue = "1") int page,
                        @ApiParam("页长") @RequestParam(value = "limit", required = false, defaultValue = "12") int limit){
        var p = new Page<Role>(page, limit);
        var qw = new QueryWrapper<Role>();
        qw.lambda()
                .orderByDesc(Role::getCreateTime);
        return p2t(roleService.page(p, qw));
    }

    @PostMapping("/role")
    @ApiOperation("创建数据")
    @Permission(authorities = "system-role-create")
    public Object create(@ApiParam("数据对象") @RequestBody DocRole object){
        var check = V.checkEmpty(baseVerify(), object);
        if (check.getBoolean(CHECK)) {
            return R.error(check.getString("message"));
        }
        // 唯一性判断
        var qw = new QueryWrapper<Role>();
        qw.lambda()
                .eq(Role::getName, object.getName());
        var only = roleService.list(qw);
        if(only.size() > 0) {
            return R.error("名称已经存在");
        }
        var model = J.o2m(object, Role.class);
        model.setCreateId(userId.get());

        model = roleService.model(model);
        if(model == null) {
            return R.error("数据创建失败");
        }else {
            return R.ok("数据创建成功", model);
        }
    }

    @PutMapping("/role/{id}")
    @ApiOperation("修改数据")
    @Permission(authorities = "system-role-update")
    public Object update(@ApiParam("数据id") @PathVariable Long id,
                         @ApiParam("数据对象") @RequestBody DocRole object){
        var model = roleService.getById(id);

        if(model == null) {
            return R.error("数据id异常");
        }
        var check = V.checkEmpty(baseVerify(), object);
        if (check.getBoolean(CHECK)) {
            return R.error(check.getString("message"));
        }

        // 唯一性判断
        var qw = new QueryWrapper<Role>();
        qw.lambda()
                .eq(Role::getName, object.getName())
                .ne(Role::getId, id);
        var only = roleService.list(qw);
        if(only.size() > 0) {
            return R.error("名称已经存在");
        }
        model = J.o2m(object, Role.class);
        model.setId(id);
        model.setUpdateId(userId.get());

        model = roleService.model(model);
        if(model == null) {
            return R.error("数据修改失败");
        }else {
            return R.ok("数据修改成功", model);
        }
    }

    @DeleteMapping("/role/{id}")
    @ApiOperation("删除数据")
    @Permission(authorities = "system-role-delete")
    public Object delete(@ApiParam("数据id") @PathVariable Long id){
        var model = roleService.getById(id);
        if(model == null) {
            return R.error("数据id异常");
        }
        if(roleService.removeById(id)) {
            return R.ok("数据删除成功", J.create("id", id));
        }
        return R.error("数据删除失败");
    }

    @GetMapping("/role/auth/{id}")
    @ApiOperation("读取角色权限")
    @Permission(authorities = "system-role-get-auth")
    public Object getAuthByRoleId(@PathVariable("id") Long id){
        // 读取当前角色权限数据
        var qw = new QueryWrapper<RoleAuth>();
        qw.lambda().eq(RoleAuth::getRoleId, id);
        var ras = roleAuthService.list(qw);

        // 读取模块
        var qwModule = new QueryWrapper<Module>();
        qwModule.lambda().orderByDesc(Module::getOrderNumber);
        var modules = moduleService.list(qwModule);

        // 读取权限菜单
        var qwAuth = new QueryWrapper<Authorities>();
        qwAuth.lambda().orderByDesc(Authorities::getOrderNumber);
        var authorities = authoritiesService.list(qwAuth);

        //组合数据
        var menu = J.list();
        if(modules.size() > 0){
            modules.stream().forEach(module -> {
                var m = J.create("id", module.getId())
                        .put("title", module.getName())
                        .put("parentId", 0)
                        .put("checkArr", checkArr(ras, module.getId()))
                        .put("children", J.list());
                var auths = getAuthByModuleId(authorities, module.getId());
                // 处理子项数据
                var parents = getAuthByParentId(auths, 0L, 0);
                var obj = J.o2l(parents);
                obj.stream().forEach(o -> {
                    var sub = getAuthByParentId(auths, o.getLong("id"), 0);
                    var subs = J.o2l(sub);
                    if(sub.size() > 0){
                        subs.stream().forEach(s -> {
                            var permission = getAuthByParentId(auths, s.getLong("id"), 1);
                            s.put("id", s.getString("id"));
                            s.put("parentId", s.getString("parentId"));
                            s.put("title", s.getString("name"));
                            s.put("checkArr", checkArr(ras, s.getLong("id")));
                            s.put("children", format2Tree(ras, permission));
                        });
                    }
                    o.put("id", o.getString("id"));
                    o.put("parentId", o.getString("moduleId"));
                    o.put("title", o.getString("name"));
                    o.put("checkArr", checkArr(ras, o.getLong("id")));
                    o.put("children", subs);
                });
                m.put("children", obj);
                menu.add(m);
            });
        }
        return R.ok(menu);
    }


    /**
     * 格式化为树格式
     * */
    private List<JSONObject> format2Tree(List<RoleAuth> ras, List<Authorities> authorities){
        var list = J.list();
        if(authorities.size() > 0){
            authorities.stream().forEach(auth -> {
                var m = J.create("id", auth.getId())
                        .put("title", auth.getName())
                        .put("parentId", auth.getParentId())
                        .put("checkArr", checkArr(ras, auth.getId()));
                list.add(m);
            });
        }
        return list;
    }
    /**
     * 读取模块菜单
     * */
    private List<Authorities> getAuthByModuleId(List<Authorities> auths, Long moduleId){
        var list = new ArrayList<Authorities>();
        if(auths.size() > 0) {
            auths.stream()
                    .filter(auth -> auth.getModuleId().equals(moduleId))
                    .forEach(auth -> {
                        list.add(auth);
                    });
        }
        return list;
    }
    /**
     * 树形选中
     * */
    private List<JSONObject> checkArr(List<RoleAuth> ras, Long authId){
        var list = J.list();
        var tem = J.create("type", 0).put("isChecked", 0);
        if(ras.size() > 0){
            var opt = ras.stream().filter(ra -> ra.getAuthId().equals(authId)).findFirst();
            if(opt.isPresent()){
                tem.put("isChecked", 1);
            }
        }
        list.add(tem);
        return list;
    }

    @PutMapping("/role/auth/{id}")
    @ApiOperation("设置权限")
    @Permission(authorities = "system-role-set-auth")
    public Object getAuthByRoleId(@PathVariable("id") Long id, @RequestBody List<DocTree> trees){

        var ras = new ArrayList<RoleAuth>();
        for(var tree:trees){
            var ra = new RoleAuth();
            ra.setAuthId(tree.getNodeId());
            ra.setRoleId(id);
            ras.add(ra);
        }
        if(roleAuthService.batch(id, ras)) {
            return R.ok("数据调整成功", J.create("id", id));
        }else {
            return R.error("数据调整失败");
        }
    }
}
